package ee.ut.maxorato_macobo.oop.mud.game;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.ListIterator;
import java.util.Map.Entry;

import ee.ut.maxorato_macobo.oop.mud.items.ContainsItems;
import ee.ut.maxorato_macobo.oop.mud.items.ItemBase;

public class GameUtils {
	public static class TypeIndexName {
		char type;
		int index;
		String name;
		
		public TypeIndexName(char type, int index, String name) {
			this.type = type;
			this.index = index;
			this.name = name;
		}
	}
	
	public static void describeItemListForPlayer(PlayerCharacter player, ArrayList<ItemBase> itemList, boolean fullSentence) {
		ListIterator<ItemBase> iti = itemList.listIterator();
		String addBeginning = fullSentence ? "\033[0;36m" : "    ";
		String addEnd = fullSentence ? "\033[0m" : "";
		
		if(iti.hasNext()) {
			LinkedHashMap<String, Integer> grouped = new LinkedHashMap<String, Integer>();
			
			while(iti.hasNext()) {
				String lookString = fullSentence ? iti.next().getLookString() : iti.next().getShortLookString();
				
				if(grouped.containsKey(lookString)) {
					grouped.put(lookString, grouped.get(lookString) + 1);
				}
				else {
					grouped.put(lookString, 1);
				}
			}
			
			Iterator<Entry<String, Integer>> itx = grouped.entrySet().iterator();
			
			while(itx.hasNext()) {
				Entry<String, Integer> entry = itx.next();
				String numCount = (entry.getValue() > 1) ? String.format(" (%2d) ", entry.getValue()) : "";
				
				player.sendTickMessage(addBeginning + numCount + entry.getKey() + addEnd);
			}
		}
		else if(!fullSentence) {
			player.sendTickMessage("    nothing.");
		}
	}
	
	public static boolean argumentHasAllSpecifier(String argument) {
		return (argument.equals("all") || GameUtils.getArgTypeIndexAndName(argument).type == 'a');
	}
	
	public static GameCharacter getTargetCharFromArgument(GameRoom room, String argument) {
		GameCharacter targetChar = null;
		
		GameUtils.TypeIndexName findInfo = GameUtils.getArgTypeIndexAndName(argument);
		char type = findInfo.type;
		
		if((type == 'x' || type == 'p') && (targetChar = room.findPlayerByName(findInfo.name)) != null);
		else if((type == 'x' || type == 'n') && (targetChar = room.findNpcByName(findInfo.name, findInfo.index)) != null);
		
		return targetChar;
	}
	
	public static ItemBase getSubItemFromArgument(ContainsItems itemListOwner, char listType, String argument) {
		ArrayList<ItemBase> foundList = getSubListFromArgument(itemListOwner, listType, argument, false);
		
		if(foundList.size() > 0) return foundList.get(0);
		else return null;
	}
	
	public static ArrayList<ItemBase> getSubListFromArgument(ContainsItems itemListOwner, char listType, String argument, boolean allowAll) {
		ArrayList<ItemBase> foundList = new ArrayList<ItemBase>();
		
		GameUtils.TypeIndexName findInfo = GameUtils.getArgTypeIndexAndName(argument);
		
		if(argument.equals("all") || findInfo.type == 'a') {
			if(allowAll) {
				String matchString = argument.equals("all") ? null : findInfo.name;
				
				for(ItemBase item : itemListOwner.getItemList()) {
					if(matchString == null || item.getName().compareToIgnoreCase(matchString) == 0) {
						foundList.add(item);
					}
				}
			}
		}
		else {
			ItemBase item = null;
			
			if((findInfo.type == 'x' || findInfo.type == listType) && (item = itemListOwner.findItemByName(findInfo.name, findInfo.index)) != null) {
				foundList.add(item);
			}
		}
		
		return foundList;
	}
	
	public static TypeIndexName getArgTypeIndexAndName(String input) {
		String findName = input;
		char type = 'x';
		int findNth = 1, dotIndex;

		if((dotIndex = input.indexOf(".")) >= 0) {
			String pre = input.substring(0, dotIndex);
			
			if(pre.charAt(0) == 'p') type = 'p';
			else if(pre.charAt(0) == 'n') type = 'n';
			else if(pre.charAt(0) == 'r') type = 'r';
			else if(pre.charAt(0) == 'i') type = 'i';
			else if(pre.equals("all")) type = 'a';
			
			if(type != 'a') {
				if(type != 'x') {
					pre = (pre.length() > 1) ? pre.substring(1) : "1";
				}
				
				findNth = GameUtils.properIntParser(pre);
			}
			
			findName = (input.length() > dotIndex + 1) ? input.substring(dotIndex + 1) : "";
		}
		
		return new TypeIndexName(type, findNth, findName);
	}
	
	public static int properIntParser(String text) {
		try {
			return Integer.parseInt(text);
		} catch(Exception e) {
			return 0;
		}
	}
	
	public static String stringCapitalize(String text) {
		String processed = "";
		
		if(text.length() > 0) processed += text.substring(0, 1).toUpperCase();
		if(text.length() > 1) processed += text.substring(1);
		
		return processed;
	}
	
	public static String shaValue(String text) {
		try {
			MessageDigest msg = MessageDigest.getInstance("SHA-1");
			Formatter frm = new Formatter();
			
			for(byte b : msg.digest(text.getBytes())) {
				frm.format("%02X", b);
			}
			
			return frm.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
	}
	
	private GameUtils() {
		
	}
}
